namespace SPDeploy.Library
{
    using System;
    using System.Collections.Generic;
    using Exceptions;
    using Helpers;
    using Interfaces;
    using Processing.Library;

    public class ProcessorRegistry : IResolver<IDeploymentTargetProcessor>
    {
        #region Fields: private

        private readonly ILogWriter _logger;
        private readonly List<IDeploymentTargetProcessor> _processors;
        private readonly IProcessorSettingsWireUp _wireUp;

        #endregion

        public ProcessorRegistry(ILogWriter logWriter, IProcessorSettingsWireUp wireUp)
        {
            _logger = logWriter;
            _wireUp = wireUp;
            _processors = new List<IDeploymentTargetProcessor>();
        }

        #region IResolver<IDeploymentTargetProcessor> Members

        public int Count
        {
            get { return _processors.Count; }
        }

        public void Register(IDeploymentTargetProcessor processor)
        {
            DetectDuplicateProcessors(processor);
            InitializeProcessor(processor);
            _processors.Add(processor);
        }

        public bool Unregister(IDeploymentTargetProcessor processor)
        {
            return _processors.Remove(processor);
        }

        public IDeploymentTargetProcessor Resolve(Type t)
        {
            foreach (IDeploymentTargetProcessor processor in _processors)
            {
                if (processor.CanProcess(t))
                {
                    return processor;
                }
            }
            return null;
        }

        #endregion

        #region Methods: private

        private void DetectDuplicateProcessors(IDeploymentTargetProcessor processor)
        {
            if (_processors.Contains(processor))
            {
                throw new DuplicateValueException();
            }
        }

        private void InitializeProcessor(IDeploymentTargetProcessor processor)
        {
            _logger.Write(LogSeverity.Verbose, "ProcessorRegistry", "Initializing processor for " + processor.Name);
            _wireUp.Wireup(new ProcessorSettingsManager(processor), _logger);
            processor.LogWriter = _logger;
        }

        #endregion
    }
}